home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / ccs / ccs-11tl.lha / lbl / xview / genial / func / spline.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-14  |  6.5 KB  |  258 lines

  1. /*
  2.  * spline.c -- draw splines
  3.  *
  4.  */
  5.  
  6. #include "reg.h"
  7. #include "display.h"
  8. #include "ui.h"
  9. #include <X11/Xlib.h>
  10. #include <stdio.h>
  11. #include <math.h>
  12.  
  13. #define THRESHOLD 1.0        /* 1.0 is better, but superplot uses 3.0 */
  14. #define round(q) ((int)((q) + .5))
  15.  
  16. /* Spline routines in here are stolen outright from
  17.  * superplot, which is: */
  18. /*************************************************************/
  19. /*                                                           */
  20. /*  Copyright (c) 1986                                       */
  21. /*  Marc S. Majka - UBC Laboratory for Computational Vision  */
  22. /*                                                           */
  23. /*  Permission is hereby granted to copy all or any part of  */
  24. /*  this program for free distribution.   The author's name  */
  25. /*  and this copyright notice must be included in any copy.  */
  26. /*                                                           */
  27. /*************************************************************/
  28.  
  29. static int lastx, lasty;
  30. static void spline(), Cspline();
  31. static struct pval pbuf[4000], *pind, *last = NULL;
  32.  
  33. static int psz = 0;
  34.  
  35. static struct dlist *vbuf, *vstart;
  36. static int v[100];
  37. static int len;
  38.  
  39. draw_spline(reg)
  40.     struct region *reg;
  41. {
  42.     sp_interp(®->r_dlist, reg->r_plist, 0);
  43.     draw_dlist(img_win->d_xid, reg->r_dlist);
  44. }
  45.  
  46. draw_clspline(reg)
  47.     struct region *reg;
  48. {
  49.     sp_interp(®->r_dlist, reg->r_plist, 1);
  50.     draw_dlist(img_win->d_xid, reg->r_dlist);
  51. }
  52.  
  53. sp_interp(pvec, ptlist, c)
  54.     struct dlist **pvec;
  55.     struct plist *ptlist;
  56.     int       c;
  57. {
  58.     struct plist *tr;
  59.  
  60.     vbuf = vstart = NULL;
  61.     len = 0;
  62.     psz = 0;
  63.     for (tr = ptlist; tr != NULL; tr = tr->next) {
  64.     v[(len * 2)] = tr->pt.x;
  65.     v[(len * 2) + 1] = tr->pt.y;
  66.     len++;
  67.     }
  68.     pind = pbuf;
  69.     spline(c, len, v);
  70.     *pvec = vstart;
  71. }
  72.  
  73. drawto(x1, y1, x2, y2)
  74.     int       x1, y1, x2, y2;
  75. {
  76.     XPoint    start, end;
  77.  
  78.     if (vbuf == NULL) {
  79.     vbuf = (struct dlist *) malloc(sizeof(struct dlist));
  80.     vbuf->next = vbuf->prev = NULL;
  81.     vstart = vbuf;
  82.     } else {
  83.     vbuf->next = (struct dlist *) malloc(sizeof(struct dlist));
  84.     vbuf->next->prev = vbuf;
  85.     vbuf->next->next = NULL;
  86.     vbuf = vbuf->next;
  87.     }
  88.     start.x = (short) x1;
  89.     start.y = (short) y1;
  90.     end.x = (short) x2;
  91.     end.y = (short) y2;
  92.     ras_line(start, end, vbuf, orig_ximg, orig_img);
  93.     /* copy from the retained point list into the current buffer of points. */
  94.     bcopy((unsigned char *) vbuf->points, (unsigned char *) pind,
  95.       sizeof(struct pval) * vbuf->len);
  96.     pind += vbuf->len;
  97.     last = pind - 1;
  98.     psz += vbuf->len;
  99. }
  100.  
  101. /* "move":  put point at x, y
  102.  * "draw":  draw a line to x, y
  103.  * "dblmove":  move, takes doubles as input
  104.  * "dbldraw":  move, takes doubles as input
  105.  */
  106.  
  107. /* This comment is from Superplot:
  108.  * based on the spline algorithms in:
  109.  * FIG : Facility for Interactive Generation of figures
  110.  * by Supoj Sutanthavibul (supoj@sally.UTEXAS.EDU)
  111.  * used with permission from the author.
  112.  */
  113.  
  114.  
  115.  
  116. /* spline():  draw splines
  117.  * Apparently n is the number of points, and v is a vector of
  118.  * numbers, length 2*n, with the even entries being x and the
  119.  * odd entries being y.  k seems to be a boolean flag:
  120.  * it seems to determine whether the spline is open or
  121.  * closed.
  122.  */
  123. static void
  124. spline(k, n, v)
  125.     int       k;        /* Flags */
  126.     int       n, *v;
  127. {
  128.     double    cx_1, cy_1, cx_2, cy_2, cx_3, cy_3, cx_4, cy_4;
  129.     double    x_1, y_1, x_2, y_2;
  130.     int       i;
  131.  
  132.     x_1 = v[0];
  133.     y_1 = v[1];
  134.     x_2 = v[2];
  135.     y_2 = v[3];
  136.  
  137.     cx_1 = (x_1 + x_2) / 2.0;
  138.     cy_1 = (y_1 + y_2) / 2.0;
  139.     cx_2 = (x_1 + 3.0 * x_2) / 4.0;
  140.     cy_2 = (y_1 + 3.0 * y_2) / 4.0;
  141.  
  142.     drawto(round(x_1), round(y_1),
  143.        lastx = round(cx_1), lasty = round(cy_1));
  144.  
  145.     for (i = 2; i < n; i++) {
  146.     x_1 = x_2;
  147.     y_1 = y_2;
  148.     x_2 = v[i * 2];
  149.     y_2 = v[i * 2 + 1];
  150.     cx_3 = (3.0 * x_1 + x_2) / 4.0;
  151.     cy_3 = (3.0 * y_1 + y_2) / 4.0;
  152.     cx_4 = (x_1 + x_2) / 2.0;
  153.     cy_4 = (y_1 + y_2) / 2.0;
  154.  
  155.     Cspline(cx_1, cy_1, cx_2, cy_2, cx_3, cy_3, cx_4, cy_4);
  156.  
  157.     cx_1 = cx_4;
  158.     cy_1 = cy_4;
  159.     cx_2 = (x_1 + 3.0 * x_2) / 4.0;
  160.     cy_2 = (y_1 + 3.0 * y_2) / 4.0;
  161.     }
  162.     if (k == 0) {
  163.     drawto(round(cx_1), round(cy_1),
  164.            lastx = round(x_2), lasty = round(y_2));
  165.     } else {
  166.     x_1 = x_2;
  167.     y_1 = y_2;
  168.     x_2 = v[0];
  169.     y_2 = v[1];
  170.     cx_3 = (3.0 * x_1 + x_2) / 4.0;
  171.     cy_3 = (3.0 * y_1 + y_2) / 4.0;
  172.     cx_4 = (x_1 + x_2) / 2.0;
  173.     cy_4 = (y_1 + y_2) / 2.0;
  174.     Cspline(cx_1, cy_1, cx_2, cy_2, cx_3, cy_3, cx_4, cy_4);
  175.     drawto(lastx, lasty,
  176.            round(x_2), round(y_2));
  177.     }
  178. }
  179.  
  180. /****************************************************************************
  181.  
  182.     The following spline drawing routine is from
  183.  
  184.     "An Algorithm for High-Speed Curve Generation"
  185.     by George Merrill Chaikin,
  186.     Computer Graphics and Image Processing, 3, Academic Press,
  187.     1974, 346-349.
  188.  
  189.     and
  190.  
  191.     "On Chaikin's Algorithm" by R. F. Riesenfeld,
  192.     Computer Graphics and Image Processing, 4, Academic Press,
  193.     1975, 304-310.
  194.  
  195. *****************************************************************************/
  196.  
  197. static void
  198. Cspline(x_1, y_1, x_2, y_2, x_3, y_3, x_4, y_4)
  199.     double    x_1, y_1, x_2, y_2, x_3, y_3, x_4, y_4;
  200. {
  201.     double    xmid, ymid, fabs();
  202.  
  203.     xmid = (x_2 + x_3) / 2.0;
  204.     ymid = (y_2 + y_3) / 2.0;
  205.  
  206.     if (fabs(x_1 - xmid) < THRESHOLD && fabs(y_1 - ymid) < THRESHOLD) {
  207.     drawto(round(x_1), round(y_1),
  208.            lastx = round(xmid), lasty = round(ymid));
  209.     } else {
  210.     Cspline(x_1, y_1, ((x_1 + x_2) / 2.0), ((y_1 + y_2) / 2.0),
  211.         ((x_2 + xmid) / 2.0), ((y_2 + ymid) / 2.0), xmid, ymid);
  212.     }
  213.  
  214.     if (fabs(xmid - x_4) < THRESHOLD && fabs(ymid - y_4) < THRESHOLD) {
  215.     drawto(round(xmid), round(ymid),
  216.            lastx = round(x_4), lasty = round(y_4));
  217.     } else {
  218.     Cspline(xmid, ymid, ((xmid + x_3) / 2.0), ((ymid + y_3) / 2.0),
  219.         ((x_3 + x_4) / 2.0), ((y_3 + y_4) / 2.0), x_4, y_4);
  220.     }
  221. }
  222.  
  223. /*****************************************************************/
  224.  
  225. char     *
  226. spline_info(reg)        /* create string containing message giving
  227.                  * info on spline */
  228.     struct region *reg;
  229. {
  230.     char      mesg[80];
  231.     int       xmax, xmin, ymax, ymin, width, height;
  232.     struct plist *tr;
  233.     
  234.     xmax = xmin = reg->r_plist->pt.x;
  235.     ymax = ymin = reg->r_plist->pt.y;
  236.  
  237.     /* find min and max of points defining the spline */
  238.  
  239.     for (tr = reg->r_plist; tr != NULL; tr = tr->next) {
  240.     if (tr->pt.x > xmax)
  241.         xmax = tr->pt.x;
  242.     if (tr->pt.x < xmin)
  243.         xmin = tr->pt.x;
  244.     if (tr->pt.y > ymax)
  245.         ymax = tr->pt.y;
  246.     if (tr->pt.y < ymin)
  247.         ymin = tr->pt.y;
  248.     }
  249.     width = xmax - xmin;
  250.     height = ymax - ymin;
  251.  
  252.     sprintf(mesg, "Spline width: %d pixels; Spline height: %d pixels ",
  253.         width, height);
  254.  
  255.     return (mesg);
  256. }
  257.  
  258.